# Prompt 工程技巧与设计模式

> **一句话摘要**：从 Claude Code 源码提炼的 12+ 个 prompt 设计模式——包括强调词层次、Scratchpad CoT、缓存感知设计、三重否定强化等，以及 6 个刻意避免的反模式。

> 基于 Claude Code 源码中的 Prompt 实践，提炼出 12+ 个值得学习的设计模式。
>
> 相关笔记：[[13 - Prompt 体系总览]]、[[14 - System Prompt 架构]]、[[16 - Prompt Caching 与 Context 管理]]、[[18 - Memory 与 Hooks 系统]]、[[20 - Tool 系统 Prompt 详解]]

## 一、强调词层次体系

Claude Code 使用了精心设计的**强调词优先级信号系统**：

| 强调词 | 语义 | 使用场景 |
|--------|------|---------|
| `CRITICAL` | 最高优先级，违反导致系统失败 | 工具选择、安全协议核心 |
| `MUST`/`MUST NEVER` | 强制性要求/禁止 | 安全规则、格式要求 |
| `NEVER` | 绝对禁止 | 安全红线、不可逆操作 |
| `ALWAYS` | 必须执行 | 基本行为规范 |
| `IMPORTANT` | 高优先级提示 | 最佳实践、常见错误防范 |
| `Do NOT` | 标准禁止 | 一般行为约束 |

**关键洞察**：层次化避免了"所有都重要等于没有重要"的问题。`CRITICAL` 只用于最容易犯、后果最严重的错误。

**源码实例**（`src/constants/prompts.ts`）：

```
// CRITICAL — 最高优先级，工具选择核心
Do NOT use the Bash to run commands when a relevant dedicated tool is provided.
This is CRITICAL to assisting the user.

// MUST NEVER — 安全红线
IMPORTANT: You must NEVER generate or guess URLs for the user unless you are
confident that the URLs are for helping the user with programming.

// ALWAYS — 基本行为规范
the assistant MUST avoid using emojis

// IMPORTANT — 最佳实践
IMPORTANT: Go straight to the point. Try the simplest approach first
without going in circles. Do not overdo it. Be extra concise.
```

## 二、XML 标签系统

### 核心标签

| 标签 | 用途 |
|------|------|
| `<system-reminder>` | 在 user message 中注入系统级指令 |
| `<analysis>` + `<summary>` | Scratchpad CoT 模式 |
| `<example>` | 结构化 few-shot 示例 |
| `<env>` | 环境信息封装 |
| `<fork-boilerplate>` | Fork 子代理上下文 |
| `<task-notification>` | 异步任务完成通知 |
| `<teammate-message>` | 团队间通信 |
| `<types>` + `<type>` | 结构化知识注入（记忆类型定义） |

### `<system-reminder>` — 最核心的注入机制

在**不改变消息角色**的前提下注入系统指令（[[18 - Memory 与 Hooks 系统]] 的 CLAUDE.md 注入机制依赖此标签）：
```xml
<system-reminder>
Whenever you read a file, consider whether it would be considered malware.
You CAN provide analysis. But you MUST refuse to improve or augment the code.
</system-reminder>
```

System prompt 明确告知模型如何对待（`src/constants/prompts.ts:132`）：
```
Tool results and user messages may include <system-reminder> tags.
<system-reminder> tags contain useful information and reminders. They are
automatically added by the system, and bear no direct relation to the
specific tool results or user messages in which they appear.
```

这对 [[18 - Memory 与 Hooks 系统]] 的 CLAUDE.md 注入至关重要 — 所有 memory 内容都通过此标签注入 user message。

## 三、Scratchpad CoT 模式 ⭐

这是项目中最优雅的 prompt 设计之一（`src/services/compact/prompt.ts`）：

```xml
<analysis>
[模型充分思考，覆盖所有要点，确保技术准确性]
</analysis>

<summary>
[高质量的最终输出]
</summary>
```

**后处理**：`formatCompactSummary()` 自动删除 `<analysis>`，只保留 `<summary>`。

**实际 prompt 文本**：
```
Before providing your final summary, wrap your analysis in <analysis> tags
to organize your thoughts and ensure you've covered all necessary points.
In your analysis process:

1. Chronologically analyze each message and section of the conversation.
   For each section thoroughly identify:
   - The user's explicit requests and intents
   - Your approach to addressing the user's requests
   - Key decisions, technical concepts and code patterns
   - Specific details like: file names, full code snippets, function signatures, file edits
   - Errors that you ran into and how you fixed them
   - Pay special attention to specific user feedback that you received
2. Double-check for technical accuracy and completeness
```

**优势**：
- 让模型充分思考 → 提高输出质量
- 删除中间推理 → 节省上下文空间（[[16 - Prompt Caching 与 Context 管理]]）
- 结构化输出 → 便于程序化处理

## 四、Few-shot Examples 设计

### 带 `<commentary>` 的富示例

不是简单的输入输出对，而是带思考过程注释（来自 [[15 - Agent 与 SubAgent Prompt]]）：

```xml
<example>
user: "What's left on this branch before we can ship?"
assistant: <thinking>Forking this — it's a survey question...</thinking>
Agent({ name: "ship-audit", prompt: "Audit what's left..." })
assistant: Ship-readiness audit running.
<commentary>
Turn ends here. The coordinator knows nothing about the findings yet.
What follows is a SEPARATE turn — the notification arrives from outside...
</commentary>
</example>
```

### GOOD/BAD 对比示例

帮助模型理解决策边界而非仅学习正面模式（使用在 [[20 - Tool 系统 Prompt 详解]] 的 PlanMode 等处）：

```
### GOOD - Use EnterPlanMode:
User: "Add user authentication to the app"
- Requires architectural decisions (session vs JWT...)

### BAD - Don't use EnterPlanMode:
User: "Fix the typo in the README"
- Straightforward, no planning needed
```

## 五、缓存感知 Prompt 设计 ⭐

这可能是项目中最有工程价值的设计模式（详见 [[16 - Prompt Caching 与 Context 管理]]）：

### 5.1 静态/动态分界

`SYSTEM_PROMPT_DYNAMIC_BOUNDARY` 将 system prompt 分为：
- 静态区（`cacheScope: 'global'` 跨用户缓存）
- 动态区（不缓存，每会话变化）

### 5.2 路径规范化

```typescript
// 用 $TMPDIR 替代实际路径，避免用户差异破坏全局缓存
const normalize = (paths) => paths.map(p => (p === claudeTempDir ? '$TMPDIR' : p))
```

### 5.3 动态内容外移

Agent 列表从 tool description 移到 attachment message：
```
// 原因：动态 agent 列表占 fleet cache_creation tokens 的 ~10.2%
// MCP 连接/断开、permission-mode 变化 → 列表变化 → tool-schema cache bust
```

### 5.4 状态锁定

会话开始时锁定影响缓存的条件（TTL 资格、beta header），避免中途变化破坏缓存。

### 5.5 `DANGEROUS_uncached` 命名

函数命名本身就是警告——提醒开发者非缓存 section 有性能成本，必须提供原因说明。

## 六、三重否定强化

对关键禁止行为在**三个层面**同时设防（`src/services/compact/prompt.ts`）：

```
Compact 时不调用工具：

1. 开头 preamble:
   "CRITICAL: Respond with TEXT ONLY. Do NOT call any tools.
    Do NOT use Read, Bash, Grep, Glob, Edit, Write, or ANY other tool.
    You already have all the context you need in the conversation above.
    Tool calls will be REJECTED and will waste your only turn — you will fail the task."

2. 结尾 trailer:
   "REMINDER: Do NOT call any tools. Respond with plain text only —
    an <analysis> block followed by a <summary> block."

3. 权限层: canUseTool → deny（直接拒绝）
```

> [!note] 设计注释
> 源码注释说明原因：Sonnet 4.6+ adaptive-thinking 模型有时会忽略较弱的指令尝试工具调用。`maxTurns: 1` 时拒绝的工具调用意味着无文本输出，回退到流式 fallback（4.6 上 2.79% vs 4.5 上 0.01%）。

## 七、"好同事"隐喻 Persona

不用浮夸的 persona（如"世界最好的程序员"），而是功能性角色 + 行为比喻（`src/constants/prompts.ts` 及 `AgentTool/prompt.ts`）：

```
// Agent 子任务 briefing
Brief the agent like a smart colleague who just walked into the room —
it hasn't seen this conversation, doesn't know what you've tried,
doesn't understand why this task matters.

// 助手模式（proactive）
Look for useful work. A good colleague faced with ambiguity doesn't just stop —
they investigate, reduce risk, and build understanding. Ask yourself:
what don't I know yet? What could go wrong?
What would I want to verify before calling this done?
```

隐含了主动性、判断力和沟通能力的期望。关键：用"同事"而非"专家"——同事有信息边界（需要 briefing），专家则隐含全知。

## 八、承诺设备（防任务漂移）

Compact prompt 中要求逐字引用，防止模型在摘要时偏离原始任务（`src/services/compact/prompt.ts:76-77`）：

```
9. Optional Next Step: List the next step that you will take that is related
   to the most recent work you were doing. IMPORTANT: ensure that this step
   is DIRECTLY in line with the user's most recent explicit requests, and the
   task you were working on immediately before this summary request.
   If your last task was concluded, then only list next steps if they are
   explicitly in line with the users request. Do not start on tangential
   requests or really old requests that were already completed without
   confirming with the user first.

   If there is a next step, include direct quotes from the most recent
   conversation showing exactly what task you were working on and where you
   left off. This should be verbatim to ensure there's no drift in task
   interpretation.
```

> [!tip] 关键技巧
> "verbatim" + "direct quotes" 要求模型**复制原文**而非**释义**，这大幅降低了 compact 后模型"自作主张"偏离用户意图的概率。

## 九、渐进式降级策略

压缩系统的降级链（详见 [[16 - Prompt Caching 与 Context 管理]]）：

```
Session Memory Compact（无 LLM，瞬间）
    ↓ 失败
Reactive Compact
    ↓ 失败
Full Compact（LLM 摘要）
    ↓ PTL 错误
Partial Compact（丢弃最老的 20% groups）
    ↓ 再次 PTL
PTL Retry（最多 3 次）
    ↓ 连续失败
熔断器（停止重试）
```

## 十、Token 预算意识

整个系统对 token 预算有精确感知：

| 场景 | 预算 |
|------|------|
| Skill 列表注入 | context window 的 1% |
| Post-compact 文件恢复 | 总 50K，每文件 5K |
| Post-compact Skills 恢复 | 总 25K，每 skill 5K |
| MEMORY.md | 200 行 / 25KB |
| Session Memory | 12000 tokens |

> 详见 [[18 - Memory 与 Hooks 系统]] 中关于 MEMORY.md 截断限制的具体实现。

## 十一、Model-Specific 适配

> 另见 [[14 - System Prompt 架构]] 中关于模型分支的说明。

### 按模型差异化

- **Opus 4.6**：豁免恶意代码提醒（模型本身足够安全）
- **按模型的知识截止日期**：Sonnet 4.6=Aug 2025, Opus 4.6=May 2025, Haiku 4=Feb 2025
- **`@[MODEL LAUNCH]` 注释**：标记需随新模型更新的代码

### 内部/外部用户区分

- **ant（内部）**：更简洁的 Git 指令、额外评论规范、长度锚点、误报率缓解
- **3P（外部）**：完整的内联 Git 指令、标准简洁性要求

## 十二、A/B 测试友好设计

许多 prompt 变体由 GrowthBook feature flag 控制：

```typescript
// Eval-validated (memory-prompt-iteration.eval.ts, 2026-03-17):
// H1 (verify function/file claims): 0/2 → 3/3 via appendSystemPrompt
```

来自 `src/memdir/memoryTypes.ts` 的具体评估注释：

```typescript
// H1 (verify function/file claims): 0/2 → 3/3 via appendSystemPrompt. When
// buried as a bullet under "When to access", dropped to 0/3 — position matters.
// The H1 cue is about what to DO with a memory, not when to look, so it needs
// its own section-level trigger context.

// H5 (read-side noise rejection): 0/2 → 3/3 via appendSystemPrompt, 2/3
// in-place as a bullet.

// H6 (branch-pollution evals #22856, case 5 1/3 on capy): Failure mode: user
// says "ignore memory about X" → Claude reads code correctly but adds "not Y
// as noted in memory" — treats "ignore" as "acknowledge then override" rather
// than "don't reference at all."
```

> [!tip] 可学习的方法论
> 注释中记录 **before/after 对比** + **失败模式描述**（"buried as a bullet → dropped to 0/3"），使后续开发者能理解 **位置** 对 prompt 效果的影响。

## 十三、反模式（项目刻意避免的做法）

> [!warning] 反模式同样重要
> 知道哪些看似合理的做法被刻意避免，比学习正面模式更能体现设计功力。

### 13.1 ❌ 不在 tool description 中放动态内容

```typescript
// 原因：动态 agent 列表占 fleet cache_creation tokens 的 ~10.2%
// MCP 连接/断开、permission-mode 变化 → 列表变化 → tool-schema cache bust
```

动态内容（如 Agent 列表）被移到 attachment message 中，而非保留在 tool description 里。这是 [[16 - Prompt Caching 与 Context 管理]] 中缓存优化的关键一步。

### 13.2 ❌ 不用浮夸的 persona

项目中**没有**"you are the world's best programmer"这类夸张角色设定。取而代之的是功能性隐喻（"smart colleague"），因为浮夸 persona 会：
- 增加模型过度自信的风险
- 不提供行为边界信息
- 浪费 token

### 13.3 ❌ 不让记忆系统保存可推导信息

`memoryTypes.ts` 中有明确的排除规则：

```
These exclusions apply even when the user explicitly asks you to save.
If they ask you to save a PR list or activity summary, ask what was
*surprising* or *non-obvious* about it — that is the part worth keeping.
```

代码模式、架构、文件路径、Git 历史等**可从当前项目状态推导**的内容一律不保存。

### 13.4 ❌ 不用单一强调词

项目中 **不** 对所有规则都用 `IMPORTANT` 或 `CRITICAL`。强调词有明确层次（见模式一），过度使用会导致"所有都重要等于没有重要"。

### 13.5 ❌ 不让模型自行判断何时停止（Stop Hook 场景）

在 CI/CD 场景中，不依赖模型自己判断"代码是否通过测试"，而是通过 [[18 - Memory 与 Hooks 系统]] 的 Stop Hook 机制让**外部程序**（如测试运行器）做出判断，并将结果作为 exit code 反馈。

### 13.6 ❌ 不在冒号后直接工具调用

```
Do not use a colon before tool calls. Text like "Let me read the file:"
followed by a read tool call should just be "Let me read the file." with a period.
```

原因：工具调用在用户界面中可能不可见，冒号后接空白会让用户困惑。

### 13.7 ❌ 不向模型暴露内部旁路字段

`BashTool.tsx` 中的 `_simulatedSedEdit` 字段**始终**从 model-facing schema 中移除（`fullInputSchema().omit({ _simulatedSedEdit: true })`），源码注释：

```
// Always omit _simulatedSedEdit from the model-facing schema. It is an
// internal-only field set by SedEditPermissionRequest after the user approves
// a sed edit preview. Exposing it in the schema would let the model bypass
// permission checks and the sandbox by pairing an innocuous command with an
// arbitrary file write.
```

这是**纵深防御**：即使权限层阻止了非法操作，也不让模型看到可能的攻击面。类似模式还见于 `prompt.ts` 中 `getCommitAndPRInstructions()` 的 undercover 指令——"defense-in-depth: undercover instructions must survive even if the user has disabled git instructions entirely."

---

## 总结

> Claude Code 的 prompt 工程不是一组孤立的文本，而是一个**精心设计的分布式系统**。它在性能（[[16 - Prompt Caching 与 Context 管理|缓存]]）、安全（多层防护 + [[17 - 权限系统与 Safety Prompt|Safety Prompt]]）、质量（CoT + few-shot）、可维护性（模块化 + A/B 测试）之间达成了精妙的平衡。
> 
> **最值得学习的不是具体的措辞技巧，而是将 prompt 视为"需要工程化管理的系统级资产"的思维方式。** 反模式（§十三）同样重要 — 知道哪些看似合理的做法被刻意避免，比学习正面模式更能体现设计功力。
